package com.fingard.dsp.bank.directbank.allinpay02;

import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.NotifySet;
import com.fingard.dsp.bank.directbank.bankInterface.IAcceptNotice;
import com.fingard.dsp.bank.reqrespobj.ReqRespHeader;
import com.fingard.dsp.bank.reqrespobj.contract.ContractState;
import com.fingard.dsp.bank.reqrespobj.qryrefund.RetAtsQryRefund;
import com.fingard.dsp.bank.reqrespobj.qryrefund.detail.RetAtsRefundDetail;
import com.fingard.generalobj.NoticeReq;
import com.fingard.generalobj.NoticeResp;
import com.fingard.io.FileHelper;
import com.fingard.net.WebRequest;
import com.fingard.net.listener.SocketReceiver;
import com.fingard.text.StringHelper;
import com.fingard.text.UrlHelper;
import com.fingard.xml.XmlTextWriter;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import org.apache.commons.lang.SerializationUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.net.URLDecoder;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

public class AllInPay02AcceptNotice extends AllInPay02Base implements IAcceptNotice {

    public NoticeResp dealNotice(NoticeReq pNtReq) throws Exception {
        String p_req = pNtReq.getReqString();
        // 通联通知需要先进行URL解码
        p_req = URLDecoder.decode(p_req, "utf-8");
        if (p_req.contains("SIGNTYPE") && p_req.contains("SIGNMODE")) {
            return dealContractNotice(pNtReq);
        } else {
            return dealQryRefundNotice(pNtReq);
        }
    }

    //退票通知
    public NoticeResp dealQryRefundNotice(NoticeReq pNtReq) throws Exception {
        NoticeResp resp = new NoticeResp();
        String p_req = pNtReq.getReqString();
        WriteBankLogLn("接收到请求：" + pNtReq.getFullString());

        // 通联退票通知需要先进行URL解码
        p_req = URLDecoder.decode(p_req, "utf-8");

        String tmpStrRet = "ERROR";
        String tmpReq = p_req;
        int idx1 = tmpReq.indexOf("GET");
        int idx2 = tmpReq.indexOf("HTTP");

        if (idx1 >= 0 && idx2 >= 0 && idx2 > idx1) {
            tmpReq = tmpReq.substring(idx1 + 3, idx2);
        }

        if (tmpReq.lastIndexOf("/") >= 0) {
            tmpReq = tmpReq.substring(tmpReq.lastIndexOf("/") + 1).trim();
        }
        if (tmpReq.indexOf("?") >= 0) {
            tmpReq = tmpReq.substring(tmpReq.indexOf("?") + 1).trim();
        }
        if (tmpReq.indexOf("&") < 0) {
            tmpStrRet = "请求数据为空";
            resp.respBytes = tmpStrRet.getBytes(pNtReq.reqCharset);
            WriteBankLogLn("响应：" + tmpStrRet);
            return resp;
        }

        Connection connection = null;
        Channel channel = null;

        try {
            TreeMap<String, String> params = new TreeMap<String, String>();

            String[] postArrays = tmpReq.split("&");
            for (String postArray : postArrays) {
                String[] kv = postArray.split("=");
                String key = postArray.split("=")[0];
                String value = "";
                if (kv.length > 1) {
                    value = postArray.split("=")[1];
                }
                params.put(key, value);
            }

            // 签名原始内容: 账号|手机号|金额|交易批次号|流水号|手续费
            //账号|手机号|金额|交易批次号|流水号|手续费
            StringBuilder verifyData = new StringBuilder();

            verifyData.append(params.get("ACCOUNT_NO")).append("|");
            verifyData.append(params.get("MOBILE")).append("|");
            verifyData.append(params.get("AMOUNT")).append("|");
            verifyData.append(params.get("BATCHID")).append("|");
            verifyData.append(params.get("SN")).append("|");
            if (StringHelper.isNullOrEmpty(params.get("POUNDAGE"))) {
                verifyData.append("0");//手续费取这个字段，如果这个字段木有值才填0
            } else {
                verifyData.append(params.get("POUNDAGE"));
            }

            boolean verifyResult = true;
            if (verifyResult) {
                // 保存至本地文件并返回"SUCCESS"
                XmlTextWriter xmlWriter = new XmlTextWriter();
                xmlWriter.writeStartElement("Refund");
                for (String key : params.keySet()) {
                    xmlWriter.writeElementString(key, params.get(key));
                }
                xmlWriter.writeEndDocument();

                String refundFilePath = createRefundFileDirectory() + File.separator + "Refund_Data_" + Format.Date10Format.format(new Date()) + ".txt";

                FileHelper.appendFile(refundFilePath, xmlWriter.toXmlString(), "utf-8");

                NotifySet ntfSet = FGBiz.dspCenter.dspConfig.getNotifySet("refundTicket");
                if ("MQ".equals(ntfSet.notifyType)) {
                    ReqRespHeader tmpHeader = new ReqRespHeader();
                    tmpHeader.bankCode = "AllInPay02";
                    tmpHeader.transType = "RefundTicket";
                    tmpHeader.transSeqID = Format.DateTime17SSSFormat.format(new Date());
                    RetAtsQryRefund retAts = new RetAtsQryRefund(tmpHeader);
                    retAts.writeStart();

                    RetAtsRefundDetail tmpRetDetail = new RetAtsRefundDetail();

                    tmpRetDetail.reqBatchNO = params.get("BATCHID");
                    tmpRetDetail.askNum = params.get("USERCODE");
                    if (StringHelper.isNullOrEmpty(tmpRetDetail.askNum)) {
                        tmpRetDetail.askNum = tmpRetDetail.reqBatchNO;
                    }
                    tmpRetDetail.recAct = params.get("ACCOUNT_NO");

                    String amount = StringHelper.amountDivide100(params.get("AMOUNT"));
                    tmpRetDetail.amount = amount;
                    if (StringHelper.hasAnyChar(params.get("SUBMITTIME"))) {
                        tmpRetDetail.submitTime = Format.DateTimeFormat.format(Format.DateTime14Format.parse(params.get("SUBMITTIME")));
                    }
                    if (StringHelper.hasAnyChar(params.get("SETTDAY"))) {
                        tmpRetDetail.refundTicketDate = Format.DateTimeFormat.format(Format.Date8Format.parse(params.get("SETTDAY")));
                    }
                    tmpRetDetail.refundTicketReason = StringHelper.joinNotEmpty("-", params.get("RETCODE"), params.get("RETMSG"));
                    if (StringHelper.isNullOrEmpty(tmpRetDetail.refundTicketReason)) {
                        tmpRetDetail.refundTicketReason = "退票";
                    } else {
                        tmpRetDetail.refundTicketReason = URLDecoder.decode(tmpRetDetail.refundTicketReason, "utf-8");
                    }


                    retAts.totleNum = "1";
                    retAts.totleAmount = amount;

                    retAts.writeRetDetail(tmpRetDetail);
                    retAts.writeEnd();
                    String notifyReqXML = retAts.getRetAtsString();

                    WriteBankLogLn("MQ通知地址：" + ntfSet.notifyHost);
                    WriteBankLogLn("MQ通知报文：" + notifyReqXML);

                    ConnectionFactory factory = new ConnectionFactory();

                    String[] ipAport = UrlHelper.pickupIpAndPort(ntfSet.notifyHost);
                    factory.setHost(ipAport[0]);
                    factory.setPort(Integer.parseInt(ipAport[1]));
                    factory.setVirtualHost(ntfSet.notifyVirtualHost);
                    factory.setUsername(ntfSet.notifyUsername);
                    factory.setPassword(ntfSet.notifyPassword);

                    connection = factory.newConnection();
                    channel = connection.createChannel();
                    channel.queueDeclare(ntfSet.notifyQueueName, true, false, false, null);

                    HashMap<String, String> mapParams = new HashMap<String, String>();

                    mapParams.put("BankCode", "AllInPay02");
                    mapParams.put("TransType", "RefundTicket");
                    mapParams.put("ReqXml", notifyReqXML);

                    channel.basicPublish("", ntfSet.notifyQueueName, null, SerializationUtils.serialize(mapParams));

                    tmpStrRet = "SUCCESS";
                } else {
                    tmpStrRet = "SUCCESS";
                    WriteBankLogLn("未配置notifySet，无需主动通知");
                }
            } else {
                tmpStrRet = "验签失败!";
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            tmpStrRet = ex.getMessage();
            WriteBankLogLn(ex);
            if (StringHelper.isNullOrEmpty(tmpStrRet)) {
                tmpStrRet = "发生异常";
            }
        } finally {
            if (channel != null) {
                channel.close();
            }
            if (connection != null) {
                connection.close();
            }
        }
        WriteBankLogLn("响应：" + tmpStrRet);
        resp.respBytes = tmpStrRet.getBytes(pNtReq.reqCharset);
        return resp;
    }

    //金服宝签约通知
    public NoticeResp dealContractNotice(NoticeReq pNtReq) throws Exception {
        if (getBankConfig().getValueAsBool("NotifyTo630")) {
            return d_dealNotice630(pNtReq);
        }
        WriteBankLogLn("回调通知开始保存本地==================");
        NoticeResp resp = new NoticeResp();
        String p_req = pNtReq.getReqString();
        WriteBankLogLn("接收到请求：" + pNtReq.getFullString());

        // 通联通知需要先进行URL解码
        p_req = URLDecoder.decode(p_req, "utf-8");
        WriteBankLogLn("签约通知报文：" + p_req);

        String tmpStrRet = "ERROR";
        String tmpReq = p_req;
        int idx1 = tmpReq.indexOf("GET");
        int idx2 = tmpReq.indexOf("HTTP");

        if (idx1 >= 0 && idx2 >= 0 && idx2 > idx1) {
            tmpReq = tmpReq.substring(idx1 + 3, idx2);
        }

        if (tmpReq.lastIndexOf("/") >= 0) {
            tmpReq = tmpReq.substring(tmpReq.lastIndexOf("/") + 1).trim();
        }
        if (tmpReq.indexOf("?") >= 0) {
            tmpReq = tmpReq.substring(tmpReq.indexOf("?") + 1).trim();
        }
        if (tmpReq.indexOf("&") < 0) {
            tmpStrRet = "请求数据为空";
            resp.respBytes = tmpStrRet.getBytes(pNtReq.reqCharset);
            WriteBankLogLn("响应：" + tmpStrRet);
            return resp;
        }

        try {
            Map params = convertToMap(tmpReq);

            if (params != null) {
                String status = params.get("STATUS").toString();
                String unifiedCode = "";
                if (StringHelper.hasAnyChar(status)) {
                    if ("0".equalsIgnoreCase(status)) {
                        status = ContractState.SUCCESS;
                        unifiedCode = "SC000";
                    } else {
                        status = ContractState.FAIL;
                        unifiedCode = getBankConfig().getMapValueByKey("contractMapping", params.get("RETCODE").toString());
                    }
                } else {
                    status = ContractState.FAIL;
                    unifiedCode = "EC801";
                }

                //签约、解约成功
                XmlTextWriter xmlWriter = new XmlTextWriter();
                xmlWriter.writeStartDocument();
                xmlWriter.writeStartElement("ATSYH");
                xmlWriter.writeStartElement("TransResp");
                xmlWriter.writeElementString("BankCode", "AllInPay02");
                xmlWriter.writeElementString("TransType", "QryContract");
                xmlWriter.writeElementClosed("TransSeqID");
                xmlWriter.writeStartElement("TransParam");
                xmlWriter.writeStartElement("DetailRecord");
                xmlWriter.writeElementString("AuthCode", params.get("TLAGRMNO").toString());
                xmlWriter.writeElementString("PayAct", params.get("ACCTNO").toString());
                xmlWriter.writeElementString("ReqSeqID", params.get("REQSN").toString());
                xmlWriter.writeElementString("SignState", status);
                xmlWriter.writeElementString("UnifiedCode", unifiedCode);
                xmlWriter.writeEndDocument();

                String CntrNoticeFilePath = createNotifyDataDirectory() + File.separator + "JFBContract_Notice_" + Format.DateTime14Format.format(new Date()) + ".txt";

                FileHelper.appendFile(CntrNoticeFilePath, xmlWriter.toXmlString(), "utf-8");
                tmpStrRet = "SUCCESS";
            } else {
                tmpStrRet = "报文格式错误";
                WriteBankLogLn("响应：" + tmpStrRet);
                resp.respBytes = tmpStrRet.getBytes(pNtReq.reqCharset);
                return resp;
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            tmpStrRet = ex.getMessage();
            WriteBankLogLn(ex);
            if (StringHelper.isNullOrEmpty(tmpStrRet)) {
                tmpStrRet = "发生异常";
            }
        }

        WriteBankLogLn("响应：" + tmpStrRet);
        resp.respBytes = tmpStrRet.getBytes(pNtReq.reqCharset);
        return resp;
    }

    public NoticeResp d_dealNotice630(NoticeReq pNtReq) throws Exception {
        WriteBankLogLn("回调通知开始上送630=======================");

        NoticeResp resp = new NoticeResp();
        String p_req = pNtReq.getReqString();
        WriteBankLogLn("接收到请求：" + pNtReq.getFullString());

        // 通联通知需要先进行URL解码
        p_req = URLDecoder.decode(p_req, "utf-8");
        WriteBankLogLn("签约通知报文：" + p_req);

        String tmpStrRet = "ERROR";
        String tmpReq = p_req;
        int idx1 = tmpReq.indexOf("GET");
        int idx2 = tmpReq.indexOf("HTTP");

        if (idx1 >= 0 && idx2 >= 0 && idx2 > idx1) {
            tmpReq = tmpReq.substring(idx1 + 3, idx2);
        }

        if (tmpReq.lastIndexOf("/") >= 0) {
            tmpReq = tmpReq.substring(tmpReq.lastIndexOf("/") + 1).trim();
        }
        if (tmpReq.indexOf("?") >= 0) {
            tmpReq = tmpReq.substring(tmpReq.indexOf("?") + 1).trim();
        }
        if (tmpReq.indexOf("&") < 0) {
            tmpStrRet = "请求数据为空";
            resp.respBytes = tmpStrRet.getBytes(pNtReq.reqCharset);
            WriteBankLogLn("响应：" + tmpStrRet);
            return resp;
        }

        try {
            Map params = convertToMap(tmpReq);

            if (params != null) {
                String status = params.get("STATUS").toString();
                String unifiedCode = "";
                if (StringHelper.hasAnyChar(status)) {
                    if ("0".equalsIgnoreCase(status)) {
                        status = ContractState.SUCCESS;
                        unifiedCode = "SC000";
                    } else {
                        status = ContractState.FAIL;
                        unifiedCode = getBankConfig().getMapValueByKey("contractMapping", params.get("RETCODE").toString());
                    }
                } else {
                    status = ContractState.FAIL;
                    unifiedCode = "EC801";
                }

                //上送630
                XmlTextWriter xmlWriter = new XmlTextWriter();
                xmlWriter.writeStartDocument();
                xmlWriter.writeStartElement("ATSYH");
                xmlWriter.writeStartElement("TransResp");
                xmlWriter.writeElementString("BankCode", "AllInPay02");
                xmlWriter.writeElementString("TransType", "ContractNotify");
                xmlWriter.writeElementString("TransSeqID", "");
                xmlWriter.writeStartElement("TransParam");
                xmlWriter.writeStartElement("DetailRecord");
                xmlWriter.writeElementString("RespCode", "0");
                xmlWriter.writeElementString("RespInfo", params.get("RETMSG").toString());
                xmlWriter.writeElementString("ReqSeqID", params.get("REQSN").toString());
                xmlWriter.writeElementString("PayAct", params.get("ACCTNO").toString());
                xmlWriter.writeElementString("SignDate", params.get("NOTIFYTIME").toString());
                xmlWriter.writeElementString("SourceNoteCode", "");
                xmlWriter.writeElementString("PolicyNo", "");
                xmlWriter.writeElementString("OppActName", "");
                xmlWriter.writeElementString("CertType", "");
                xmlWriter.writeElementString("CertNumber", "");
                xmlWriter.writeElementString("CellPhone", "");
                xmlWriter.writeElementString("CurType", "");
                xmlWriter.writeElementString("NoteMoney", "");
                xmlWriter.writeElementString("BusType", "");
                xmlWriter.writeElementString("SignState", status);
                xmlWriter.writeElementString("UnifiedCode", unifiedCode);
                xmlWriter.writeElementString("AuthCode", params.get("TLAGRMNO").toString());
                xmlWriter.writeEndDocument();

                String url = bankFront.getUrl("JFBCntrNotifyTo630");
                WriteBankLogLn("通知630的地址：" + url);
                String p_reqStr = xmlWriter.toXmlString();
                WriteBankLogLn("通知630的报文：" + p_reqStr);
                byte[] tmpToWriteBytes = p_reqStr.getBytes(getCharset());
                WebRequest tmpWebRequest = new WebRequest(url);
                tmpWebRequest.setConnectTimeout(600000);
                tmpWebRequest.setRequestProperty("Content-Type", "application/xml");
                tmpWebRequest.setRequestProperty("Connection", "keep-alive");
                tmpWebRequest.upload(tmpToWriteBytes, "UTF-8");
            } else {
                tmpStrRet = "报文格式错误";
                WriteBankLogLn("响应：" + tmpStrRet);
                resp.respBytes = tmpStrRet.getBytes(pNtReq.reqCharset);
                return resp;
            }
        } catch (Exception e) {
            WriteBankLogLn(e);
        }
        return resp;
    }

    @Override
    public void getContentLength(SocketReceiver p_receiver) throws Exception {

    }
}
